/*
 *  Copyright (c) 2015 The WebRTC project authors. All Rights Reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree.
 */

'use strict';

////////////////////////////////////////////////////  var defined

var constraints = {};

if (isChrome) {
    constraints = {
        video: {
            mandatory: {
                chromeMediaSource: 'desktop',
                maxWidth: 1920,
                maxHeight: 1080,
                maxFrameRate: 10,
                minAspectRatio: 1.77
            }
        }
    };
}

if (isFirefox) {
    constraints = {
        "video": {
            "mozMediaSource": "window",
            "mediaSource": "window",
        }
    };
}

var configuration = {
    iceServers: [{
        urls: 'stun:yuexi.info',
        username: "zzl",
        credential: "123",
        credentialType: "password"
    }, {
        urls: 'turn:yuexi.info',
        username: "zzl",
        credential: "123",
        credentialType: "password"
    }]
};

var socket;
var rtcPeerConnections = [];

var video1 = document.querySelector('video#video1');
var startButton = document.getElementById('startButton');
var callButton = document.getElementById('callButton');
var hangupButton = document.getElementById('hangupButton');


var offerOptions = {
    offerToReceiveAudio: 1,
    offerToReceiveVideo: 1
};


//////////////////////////////////////////////////// 
//////////////////////////////////////////////////// 
//////////////////////////////////////////////////// 
//////////////////////////////////////////////////// 
//////////////////////////////////////////////////// 

function makeId() {
    var text = "";
    var possible = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";

    for (var i = 0; i < 5; i++)
        text += possible.charAt(Math.floor(Math.random() * possible.length));

    return text + (new Date()).getTime();
}

function insertParam(key, value) {
    key = encodeURI(key);
    value = encodeURI(value);

    var kvp = document.location.search.substr(1).split('&');

    var i = kvp.length;
    var x;
    while (i--) {
        x = kvp[i].split('=');

        if (x[0] == key) {
            x[1] = value;
            kvp[i] = x.join('=');
            break;
        }
    }

    if (i < 0) {
        kvp[kvp.length] = [key, value].join('=');
    }

    //this will reload the page, it's likely better to store this until finished
    document.location.search = kvp.join('&');
}

function setCookie(name, value, days) {
    var expires = "";
    if (days) {
        var date = new Date();
        date.setTime(date.getTime() + (days * 24 * 60 * 60 * 1000));
        expires = "; expires=" + date.toUTCString();
    }
    document.cookie = name + "=" + (value || "") + expires + "; path=/";
}

function getCookie(name) {
    var nameEQ = name + "=";
    var ca = document.cookie.split(';');
    for (var i = 0; i < ca.length; i++) {
        var c = ca[i];
        while (c.charAt(0) == ' ') c = c.substring(1, c.length);
        if (c.indexOf(nameEQ) == 0) return c.substring(nameEQ.length, c.length);
    }
    return null;
}

function eraseCookie(name) {
    document.cookie = name + '=; Max-Age=-99999999;';
}

// /////////////////////////////////////////////////////=========================================================
// /////////////////////////////////////////////////////=========================================================
// /////////////////////////////////////////////////////=========================================================

(function initWebSocket() {
    var url_string = window.location.href;
    var url = new URL(url_string);
    var r = url.searchParams.get("r");
    if (!r)
        insertParam('r', makeId());
    else {
        initNickName();
        initRoomAndJoin(r);
    }
})();

function initNickName() {
    if (!getCookie('nickName')) {
        while (true) {
            var name = prompt("Please enter your name", "");
            if (name) {
                setCookie('nickName', name, 360);
                break;
            }
        }
    }
}

var functions = {
    connect: function(params) {
        var pc01Idx = rtcPeerConnections.findIndex(pc => pc.target == params.socket);
        if (pc01Idx >= 0) {
            rtcPeerConnections[pc01Idx].close();
            rtcPeerConnections.splice(pc01Idx, 1);
        }
        var pc01 = new RTCPeerConnection(configuration);
        pc01.target = params.socket;

        var dataChannel = pc01.createDataChannel('default');
        pc01.dataChannel = dataChannel;

        pc01.onnegotiationneeded = event => pc01.createOffer(offerOptions)
            .then(offer => pc01.setLocalDescription(offer))
            .then(() => socket.emit('signal', JSON.stringify({
                to: pc01.target,
                command: 'answer',
                params: {
                    socket: socket.id,
                    sdp: pc01.localDescription
                }
            })));

        pc01.onaddstream = function(event) {
            console.log('onaddstream', arguments);
            video1.srcObject = event.stream;
        };



        dataChannel.onopen = function() {
            console.log('Data channel is open and ready to be used.');
        };
        dataChannel.onmessage = function(msg) {
            console.log('channel.onmessage:', msg);
        };
        pc01.ondatachannel = function(event) {
            console.log('ondatachannel: ', arguments);
            pc01.dataChannel = event.channel;
            event.channel.onopen = function() {
                console.log('Data channel is open and ready to be used.');
            };
            event.channel.onmessage = function(msg) {
                console.log('channel.onmessage:', msg);
            };
        };

        pc01.ontrack = function(event) {
            console.log('==== ontrack: ', event);
            video1.srcObject = event.streams[0];
            startButton.disabled = true;
        };

        pc01.onicecandidate = function(event) {
            console.log('onicecandidate ===> ', arguments);
            if (event.candidate)
                socket.emit('signal', JSON.stringify({
                    to: pc01.target,
                    command: 'addIceCandidate',
                    params: {
                        socket: socket.id,
                        candidate: event.candidate
                    }
                }));
        };

        pc01.oniceconnectionstatechange = function(event) {
            console.log('oniceconnectionstatechange: ', pc01.iceConnectionState);
        };

        pc01.onconnectionstatechange = function(event) {
            console.log('onconnectionstatechange: ', pc01.connectionState);
        };

        rtcPeerConnections.push(pc01);



        pc01.createOffer(
                offerOptions
            ).then(
                function(sdp) {
                    console.log(sdp);
                    return pc01.setLocalDescription(sdp).then(() => console.log('connect -- setLocalDescription -- done.'));
                }
            )
            .then(() => {
                socket.emit('signal', JSON.stringify({
                    to: pc01.target,
                    command: 'answer',
                    params: {
                        socket: socket.id,
                        sdp: pc01.localDescription
                    }
                }));
            })
            .catch(function() {
                console.error(arguments);
            });
    },

    answer: function(params) {
        var pc01Idx = rtcPeerConnections.findIndex(pc => pc.target == params.socket);
        if (pc01Idx >= 0) {
            rtcPeerConnections[pc01Idx].close();
            rtcPeerConnections.splice(pc01Idx, 1);
        }
        var pc01 = new RTCPeerConnection(configuration);
        pc01.target = params.socket;

        

        pc01.onaddstream = function(event) {
            console.log('onaddstream', arguments);
            video1.srcObject = event.stream;
        };

        pc01.ondatachannel = function(event) {
            console.log('ondatachannel: ', arguments);
            pc01.dataChannel = event.channel;
            event.channel.onopen = function() {
                console.log('Data channel is open and ready to be used.');
            };
            event.channel.onmessage = function(msg) {
                console.log('channel.onmessage.', msg);
            };
        };

        pc01.ontrack = function(event) {
            console.log('ontrack: ', arguments);
            video1.srcObject = event.streams[0];
            startButton.disabled = true;
        };

        pc01.onicecandidate = function(event) {
            console.log('onicecandidate ===> ', arguments);
            if (event.candidate)
                socket.emit('signal', JSON.stringify({
                    to: pc01.target,
                    command: 'addIceCandidate',
                    params: {
                        socket: socket.id,
                        candidate: event.candidate
                    }
                }));
        };

        pc01.oniceconnectionstatechange = function(event) {
            console.log('oniceconnectionstatechange: ', pc01.iceConnectionState);
        };

        pc01.onconnectionstatechange = function(event) {
            console.log('onconnectionstatechange: ', pc01.connectionState);
        };

        rtcPeerConnections.push(pc01);


        pc01.setRemoteDescription(new RTCSessionDescription(params.sdp))
            .then(() => {
                console.log('answer -- setRemoteDescription -- done.');
                return pc01.createAnswer(offerOptions);
            })
            .then(
                function(sdp) {
                    console.log('createAnswer: ', sdp);
                    return pc01.setLocalDescription(sdp)
                        .then(() => {
                            console.log('answer -- setLocalDescription -- done.');
                        });
                }
            )
            .then(() => {
                socket.emit('signal', JSON.stringify({
                    to: pc01.target,
                    command: 'answer2',
                    params: {
                        socket: socket.id,
                        sdp: pc01.localDescription
                    }
                }));
            })
            .catch(err => console.error(err));

    },

    answer2: function(params) {
        var pc01 = rtcPeerConnections.find(pc => pc.target == params.socket);
        pc01.setRemoteDescription(new RTCSessionDescription(params.sdp)).then(() => console.log('answer2 -- setRemoteDescription -- done.'));
    },

    addIceCandidate: function(params) {
        var pc01 = rtcPeerConnections.find(pc => pc.target == params.socket);
        let candidate = new RTCIceCandidate(params.candidate);
        pc01.addIceCandidate(candidate).then(() => console.log('addIceCandidate done.', arguments));
    }
};

function initRoomAndJoin(roomId) {
    socket = io();
    socket.on('connect', function() {
        socket.emit('join room', roomId);
        initPeerConnections(roomId);
    });

    socket.on('signal', function(signalObj) {

        var signalObj2 = JSON.parse(signalObj);
        console.log(signalObj2);
        if (signalObj2.command && functions[signalObj2.command]) {
            functions[signalObj2.command](signalObj2.params);
        }
    });

    socket.on('disconnect', (reason) => {
        console.log(reason);
    });
}

function initPeerConnections(roomId) {
    socket.emit('signal', JSON.stringify({
        to: roomId,
        command: "connect",
        params: {
            socket: socket.id
        }
    }));
}



hangupButton.disabled = true;

startButton.onclick = start;


var localStreamAudio;
var localStreamShare;

function start() {

    navigator.mediaDevices.getUserMedia(constraints)
        .then(function(stream) {
            trace('Received local stream');
            rtcPeerConnections.forEach(pc01 => {
                // pc01.addStream(stream);
                stream.getTracks().forEach(track => {
                    pc01.addTrack(track, stream);
                    console.log('added track: ', pc01, track, stream);
                });
            });
            // video1.srcObject = stream;
            // localStreamShare = stream;
        })
        .catch(function(e) {
            console.log('getUserMedia() error: ', e);
        });
}